package main

import (
	"fmt"
	"strings"
)

func main() {
	{
		var a [2]string
		a[0] = "Hello"
		a[1] = "World"
		fmt.Println(a[0], a[1])
		fmt.Println(a)

		primes := [6]int{2, 3, 5, 7, 11, 13}
		fmt.Println(primes)

		sub_primes := primes[1:4] // 3, 5, 7
		fmt.Println(sub_primes)

		sub_primes[0] = 100
		fmt.Println(sub_primes) // 100, 5, 7
		fmt.Println(primes)     // 2, 100, 5, 7, 11, 13
	}
	// Slices are like references to arrays
	{
		q := []int{2, 3, 5, 7, 11, 13}
		fmt.Println(q)
	}
	{
		s := []struct {
			i int
			b bool
		}{
			{2, true},
			{3, false},
			{5, true},
			{7, false},
			{11, true},
			{13, false},
		}
		fmt.Println(s)
	}
	{
		s := []int{2, 3, 5, 7, 11, 13}
		printSlice(s) // len=6 cap=6 [2 3 5 7 11 13]

		s = s[:0]
		printSlice(s) // len=0 cap=6 []

		s = s[:4]
		printSlice(s) // len=4 cap=6 [2 3 5 7]

		s = s[2:]
		printSlice(s) // len=2 cap=4 [5 7]

		s[0] = 100
		printSlice(s) // len=2 cap=4 [100 7]
	}

	{
		var s []int
		printSlice(s) // len=0 cap=0 []
		if s == nil {
			fmt.Println("nil!") // nil!
		}
	}

	{
		a := make([]int, 5) // make a slice with len=5, cap=5
		printSlice(a)       // len=5 cap=5 [0 0 0 0 0]

		b := make([]int, 0, 5) // make a slice with len=0, cap=5
		printSlice(b)          // len=0 cap=5 []

		// change b[i]
		for i := 0; i < 8; i++ {
			b = append(b, i)
		}
		printSlice(b) // len=8 cap=10 [0 1 2 3 4 5 6 7]

		c := b[:2]
		printSlice(c) // len=2 cap=10 [0 1]

		d := c[2:5]
		printSlice(d) // len=3 cap=8 [2 3 4]

		e := d[0:7]
		printSlice(e) // len=7 cap=8 [2 3 4 5 6 7 0]
	}

	{
		board := [][]string{
			[]string{"_", "_", "_"},
			[]string{"_", "_", "_"},
			[]string{"_", "_", "_"},
		}
		board[0][0] = "X"
		board[2][2] = "O"
		board[1][2] = "X"
		board[1][0] = "O"
		board[0][2] = "X"
		for i := 0; i < len(board); i++ {
			fmt.Printf("%s\n", strings.Join(board[i], " "))
		}
	}
}

func printSlice(s []int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
